#include "API.h"
#include <assert.h>

int API::getTeleportNode() {
    if(cost_limit !=  NO_COST_LIMIT && total_cost >= cost_limit) return -1;
    if(Graph->Empty())
        return -1;
    else if(Graph->GetEdges() == 0){
        return Graph->GetRndNId();
    }
	TNEGraph::TEdgeI EI = Graph->GetRndEI();
    int node_id = EI.GetDstNId();
    Discover->AddNode(node_id);
    total_cost++;
#ifdef DEBUG
    printf("Teleport to node %d;\t Total cost used %d\n", node_id, total_cost);
#endif
    return node_id;
}

void API::getFollowers(int NId, TIntV& TVec, int index) {
    if(cost_limit !=  NO_COST_LIMIT && total_cost >= cost_limit) return;

    assert(Discover->IsNode(NId));
    TNEGraph::TNodeI NI = Graph->GetNI(NId);
    int count = 0;
    for(int i=index ;i < NI.GetInDeg() && count < C;i++){
        count++;
        int node_id = NI.GetInNId(i);
        Discover->AddNode(node_id);
        Discover->AddEdge(node_id, NId);
        TVec.Add(node_id);
    }
    if(cache && index == 0) {
        if(asked[0].IsKey(NId))
            total_cost--;
        else
            asked[0].AddKey(NId);
    }
    total_cost++;
#ifdef DEBUG_FOLLOW
    printf("getFollowers(node,index,retLen) = (%d,%d,%d);\t Total cost used %d\n", NId, index, TVec.Len(), total_cost);
#endif
}

void API::getFollowees(int NId, TIntV& TVec, int index) {
    if(cost_limit !=  NO_COST_LIMIT && total_cost >= cost_limit) return;

    assert(Discover->IsNode(NId));
    TNEGraph::TNodeI NI = Graph->GetNI(NId);
    int count = 0;
    for(int i=index ;i < NI.GetOutDeg() && count < C;i++){
        count++;
        int node_id = NI.GetOutNId(i);
        Discover->AddNode(node_id);
        Discover->AddEdge(NId, node_id);
        TVec.Add(node_id);
    }
    if(cache && index == 0) {
        if(asked[1].IsKey(NId))
            total_cost--;
        else
            asked[1].AddKey(NId);
    }
    total_cost++;
#ifdef DEBUG_FOLLOW
    printf("getFollowees(node,index,retLen) = (%d,%d,%d);\t Total cost used %d\n", NId, index, TVec.Len(), total_cost);
#endif
}

TIntPr API::getDegree(int NId) {
    if(cost_limit !=  NO_COST_LIMIT && total_cost >= cost_limit) return TIntPr(-1,-1);

    TIntPr TPair;
    assert(Discover->IsNode(NId));
    TNEGraph::TNodeI NI = Graph->GetNI(NId);
    TPair.Val1 = NI.GetInDeg();
    TPair.Val2 = NI.GetOutDeg();
    total_cost++;
    if (cache) {
        if (asked[2].IsKey(NId)) total_cost--;
        else asked[2].AddKey(NId);
    }
#ifdef DEBUG
    printf("getDegree(%d) = (in=%d, out=%d);\t Total cost used %d\n", NId, TPair.Val1, TPair.Val2, total_cost);
#endif
    return TPair;
}

void API::getAllFollowers(int NId, TIntV& TVec) {
  if(cost_limit !=  NO_COST_LIMIT && total_cost >= cost_limit) 
    return;

  assert(Discover->IsNode(NId));
  TNEGraph::TNodeI NI = Graph->GetNI(NId);
  TVec.Reserve(TVec.Len() + NI.GetInDeg());
  for(int i = 0; i < NI.GetInDeg();i++){
    int node_id = NI.GetInNId(i);
    Discover->AddNode(node_id);
    Discover->AddEdge(node_id, NId);
    TVec.Add(node_id);
  }
  
  total_cost += (NI.GetInDeg() / C) + 1;
}

void API::getAllFollowees(int NId, TIntV& TVec) {
  if(cost_limit !=  NO_COST_LIMIT && total_cost >= cost_limit) 
    return;

  assert(Discover->IsNode(NId));
  TNEGraph::TNodeI NI = Graph->GetNI(NId);
  TVec.Reserve(TVec.Len() + NI.GetOutDeg());
  for(int i = 0; i < NI.GetOutDeg();i++){
    int node_id = NI.GetOutNId(i);
    Discover->AddNode(node_id);
    Discover->AddEdge(NId, node_id);
    TVec.Add(node_id);
  }
  
  total_cost += (NI.GetOutDeg() / C) + 1;
}
